#ifndef LUA_STD_COMPLEX_UI
#define LUA_STD_COMPLEX_UI
#include <luaCPPSTD/config.h>
#include <vector>
#include <complex>
#include <algorithm>
/*//////

// tolua_begin
namespace std{ 
	class complex
	{
		TOLUA_TEMPLATE_BIND(TT,double,float)
		complex();
		complex(const TT& );	
		complex(const std::complex<TT>& );
		complex( TT re, TT im );
		const TT& real() const;
		const TT& imag() const;
        TT& real();
		TT& imag();


        tolua_outside TT complex_abs @ abs();
		tolua_outside TT complex_arg @ arg();

		tolua_outside std::complex<TT> add @ .add(const std::complex<TT>&);
		tolua_outside std::complex<TT> sub @ .sub(const std::complex<TT>&);
		tolua_outside std::complex<TT> mul @ .mul(const std::complex<TT>&);
		tolua_outside std::complex<TT> div @ .div(const std::complex<TT>&);

		tolua_outside std::complex<TT> add @ .add(const TT&);
		tolua_outside std::complex<TT> sub @ .sub(const TT&);
		tolua_outside std::complex<TT> mul @ .mul(const TT&);
		tolua_outside std::complex<TT> div @ .div(const TT&);

		tolua_outside std::complex<TT> add @ .add(const TT&);
		tolua_outside std::complex<TT> sub @ .sub(const TT&);
		tolua_outside std::complex<TT> mul @ .mul(const TT&);
		tolua_outside std::complex<TT> div @ .div(const TT&);
	};
$[

-- Create a Point constructor
function complex (self)
 local cobj = std.complex:new(self.re or 0, self.im or 0)
 tolua.takeownership(cobj)
 return cobj
end

$] 

};
std::complex<double> add (double , std::complex<double> );
// tolua_end
//*//////

template<class TT>
TT complex_abs(std::complex<TT>* a)
{
	return std::abs( *a );
}
template<class TT>
TT complex_arg(std::complex<TT>* a)
{
	return std::arg( *a );
}

template<class TT>
std::complex<TT> add(std::complex<TT>* a, const std::complex<TT>& b)
{
	return ( *a + b );
}

template<class TT>
std::complex<TT> sub(std::complex<TT>* a, const std::complex<TT>& b)
{
	return ( *a - b );
}
template<class TT>
std::complex<TT> mul(std::complex<TT>* a, const std::complex<TT>& b)
{
	return ( *a * b );
}
template<class TT>
std::complex<TT> div(std::complex<TT>* a, const std::complex<TT>& b)
{
	return ( *a / b );
}


template<class TT>
std::complex<TT> add(std::complex<TT>* a, const TT& b)
{
	return ( *a + b );
}

template<class TT>
std::complex<TT> sub(std::complex<TT>* a, const TT& b)
{
	return ( *a - b );
}
template<class TT>
std::complex<TT> mul(std::complex<TT>* a, const TT& b)
{
	return ( *a * b );
}
template<class TT>
std::complex<TT> div(std::complex<TT>* a, const TT& b)
{
	return ( *a / b );
}


template<class T, class TT>
std::complex<TT> add(T a, const std::complex<TT>& b)
{
	return ( a + b );
}
template<class T, class TT>
std::complex<TT> sub(T a, const std::complex<TT>& b)
{
	return ( a - b );
}
template<class T, class TT>
std::complex<TT> mul(T a, const std::complex<TT>& b)
{
	return ( a * b );
}
template<class T, class TT>
std::complex<TT> div(T a, const std::complex<TT>& b)
{
	return ( a / b );
}


#endif
